/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cageballserver.io;

import cageballcommon.exceptions.CageballIOException;
import cageballcommon.exceptions.CageballParseException;
import cageballcommon.io.impl.CageballSocketIO;
import cageballcommon.messages.InitTeam;
import cageballserver.CageballClient;
import cageballserver.CageballNotifier;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.LinkedList;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author kanonas
 */
public class GameServer implements Runnable {

    private ServerSocket socket;
    private Properties confGame;
    private int port;
    private int id;
    private LinkedList<CageballClient> list;
    private Thread thread;
    private boolean running;
    private final CageballNotifier notifier;

    public GameServer(int port, Properties confGame, CageballNotifier notifier) throws IOException {
        this.port = port;
        this.confGame = confGame;
        this.notifier = notifier;

        list = new LinkedList<CageballClient>();
        running = false;
    }

    private synchronized void addClient(CageballClient client){
        list.add(client);
    }

    public void run() {

        Client client;
        InitTeam tmp;
        while (running) {
            try {
                client = new Client(new CageballSocketIO(socket.accept()), id++, this);
                addClient(client);
                notifier.clientConnected(client);

                client.writeProperties(confGame);
                tmp = client.readInitTeam();
                client.setInitTeam(tmp);

                client.setClientState(ClientState.READY);

            } catch (CageballIOException ex) {
                Logger.getLogger(GameServer.class.getName()).log(Level.SEVERE, null, ex);
            } catch (CageballParseException ex) {
                Logger.getLogger(GameServer.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException ex) {
                Logger.getLogger(GameServer.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
    
    public LinkedList<CageballClient> listClients() {
        return list;
    }

    public synchronized void start() throws CageballIOException {
        try {
            running = true;
            id = 1;
            socket = new ServerSocket(port);
            thread = new Thread(this);
            thread.start();
        } catch (IOException ex) {
            throw new CageballIOException(ex.getMessage());
        }
    }

    public synchronized void stop() throws CageballIOException {
        try {
            running = false;
            thread.interrupt();
            for (CageballClient c : list) {
                try {
                    c.close();
                } catch (CageballIOException ex) {
                    Logger.getLogger(GameServer.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            list.clear();
            socket.close();
        } catch (IOException ex) {
            throw new CageballIOException(ex.getMessage());
        }
    }

    public void removeClient(CageballClient client){
        list.remove(client);

        notifier.clientConnected(client);
    }
}
